package Events;

import Events.Simple_Events.Simple_CreditChange;
import Events.Simple_Events.Simple_InsuranceDeductibleChange;
import Events.Simple_Events.Simple_IncomeChange;
import Events.Simple_Events.Simple_JobPerformanceChange;
import shared.Consts;
import shared.PlayerPortfolio;
import server.ProfessionFactory;
import java.util.Random;

/**
 * Wrapper/container for all events
 * @author Joel Garboden
 */
public interface Composite_Events
{
  /**
   * Generic event for finding money
   */
  public class FindMoney extends BaseEvent
  {
    public static int LOWER_MAGNITUDE_BOUND = 1;
    public static int UPPER_MAGNITUDE_BOUND = 100;

    int moneyMagnitude; //used to scale money found

    /**
     * Constructor for scalable money discovery event
     */
    public FindMoney()
    {
      message += "Money found.";
      moneyMagnitude = new Random().nextInt(UPPER_MAGNITUDE_BOUND);
    }

    public FindMoney(int moneyMagnitude)
    {
      this.moneyMagnitude = moneyMagnitude;
    }

    @Override
    public void execEvent(PlayerPortfolio portfolio)
    {
      portfolio.findMoney(moneyMagnitude);
    }
  }

  /**
   * Insurance deduction
   */
  public class Bonus extends BaseEvent
  {
    private double bonusPercentage;
    /**
     * Constructor for insurance deductible
     */
    public Bonus(double bonusPercentage)
    {
      this.bonusPercentage = bonusPercentage;
      message += bonusPercentage + "% bonus received.";
    }

    @Override
    public void execEvent(PlayerPortfolio portfolio)
    {
      int bonus = (int)(portfolio.salary() * bonusPercentage);
      portfolio.balanceChange(bonus);
    }
  }

  /**
   * Composite event for crashing a vehicle
   */
  public class Crashed extends CompositeEvent
  {
    private final double payCut = 0.05;
    private final double deductibleIncrease = 0.05;
    /**
     * Constructor for generic crash
     */
    public Crashed()
    {
      addEvent(new Simple_IncomeChange(-payCut));
      addEvent(new Simple_JobPerformanceChange(ProfessionFactory.MODERATE_DEMOTION_PROMOTION, 0.0));
      addEvent(new Simple_InsuranceDeductibleChange(0, deductibleIncrease));
      //TODO charge deductible
      //addEvent(new Simple_CashChange(deductibleIncrease));

      message = "You crashed and had to pay your insurance deductible. Your " +
                "base pay dropped by " + payCut + "% and your insurance " +
                "deductible went up by " + deductibleIncrease + "%. You also " +
                "got written up for the moderate failure.";
    }
  }

  /**
   * Composite event for piloting airforce one
   */
  public class PilotAirForceOne extends CompositeEvent
  {
    /**
     * Constructor
     */
    public PilotAirForceOne()
    {
      final double payIncrease = 0.20;
      final double deductibleDecrease = 0.05;

      message = "You were commisioned to be the pilot of Air Force One";

      addEvent(new Simple_IncomeChange(payIncrease));
      addEvent(new Simple_InsuranceDeductibleChange(0, deductibleDecrease));
      addEvent(new Simple_JobPerformanceChange(ProfessionFactory.MAJOR_DEMOTION_PROMOTION, 0.0));

//      message = "You were commisioned to be the pilot of Air Force One and gained a "
//                + payIncrease + "% and your insurance deductible went down by " +
//                deductibleDecrease + "%. You also got noticed for your exceptional performance.";
    }
  }

  /**
   * Generic event for finding employee fraud event
   */
  public class FoundCrookedEmployee extends CompositeEvent
  {
    final double payBonusPercentage = 0.05;
    final double deductibleDecrease = 0.05;

    /**
     * Constructor for finding crooked employees
     */
    public FoundCrookedEmployee()
    {
      addEvent(new Bonus(payBonusPercentage));
      addEvent(new Simple_InsuranceDeductibleChange(0, deductibleDecrease));
      addEvent(new Simple_JobPerformanceChange(ProfessionFactory.MODERATE_DEMOTION_PROMOTION, 0.0));

      message = "You found a crooked employee and gained a " + payBonusPercentage +
                "% bonus. Your insurance deductible went down by " + deductibleDecrease +
                "%. You also got noticed for your performance.";
    }
  }
 /**
   * Gas fire event
   */
  public class GasFire extends CompositeEvent
  {
    final double deductibleIncrease = 0.05;
    final int UPPER_BOUND = 100;
    Random r;

    /**
     * Generic constructor
     */
    public GasFire()
    {
      r = new Random();
      addEvents();
    }

    /**
     * Constructor
     * @param r
     */
    public GasFire(Random r)
    {
      this.r = r;
      addEvents();
    }

    /**
     * Adds base events to composite event
     */
    private void addEvents()
    { //make scalable to game progress
      double fireDamage = r.nextInt(UPPER_BOUND);

      addEvent(new Simple_CreditChange(0, fireDamage));
      addEvent(new Simple_InsuranceDeductibleChange(0, 0.05));
      addEvent(new Simple_InsuranceDeductibleChange(0, Consts.TEN_PERCENT));
      message = "Your business is vandalized and explodes in a fireball that " +
                "you can see from your parent's basement. You had to put $" +
                fireDamage + " and your insurance deductible on your credit " +
                "card to cover damages. Your insurance deductible went up by 5%. " +
                "The fire department concluded that it was a city accident and not your fault.";
    }
  }
}
